Prerequisites

MATLAB의 반복문에 대해 잘 이해하기 위해서는 아래의 내용에 대해 알고 오시는 것이 좋습니다.

Introduction

프로그래밍을 하다보면 작업들을 반복적으로 수행해야 할 경우가 생긴다. 여기서 말하는 반복 작업이란, 1부터 100까지 숫자를 더하는 것과 같이 아주 단순한 반복 작업 외에도 수치 해석이나 시뮬레이션 등의 고 수준의 알고리즘을 구현할 때에도 꼭 필요한 기능이다. MATLAB에서는 크게 for-end 구조(흔히 for 문)와 while-end 구조(흔히 while 문)의 두 가지 구조를 이용해 반복 작업을 수행할 수 있다.

for-end 구조

for-end 구조는 흔히 for 문(文)이라고도 불리고, 흔히 몇 번 반복할지 그 횟수를 지정하여 특정 명령어 그룹을 반복하여 수행할 수 있다. MATLAB의 for 문은 하나의 for라는 명령 문구에 end 문구가 하나씩 쌍을 이루는 식으로 구성되어 있으며, for 뒤에 iterator를 벡터 형식으로 정의하는 문법을 가지고 있다. 이 문법은 상당히 독특한 형태라는 생각이 들 수 있으나, 반복문에 대한 pseudo-code 형식을 최대한 모방하면서 MATLAB의 기본이 되는 벡터를 활용한 구조라는 점을 생각해본다면 충분히 MATLAB 스러운 철학하에 고안된 구조라고 생각할 수 있다.

기본적인 for 문의 구조는 아래와 같다.

for i = 1:10
    disp(i)
end

위 코드 섹션을 수행해보면 1부터 10까지 차례대로 숫자를 출력해주는 것을 알 수 있다. 만약, for 문을 쓰지 않고 동일한 작업을 수행하려고 했다면 disp(1)부터 disp(10)까지 한 줄 씩 코드로 총 10줄을 작성해야 했을 것이다.

또 하나 주목해서 볼만한 점은 앞서 언급했듯이 MATLAB의 for 문에서는 벡터를 활용한다는 점이다. 다시 말하면 위 코드 섹션에서 i = 1:10에 해당하는 부분이 벡터를 활용한 부분인데, 1:10이라는 값은 콜론 연산자를 이용하여 벡터 [1, 2, ..., 10]을 달리 쓴 것이다. 그러므로 아래와 같이 써도 동일한 효과를 발휘한다.

for i = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    disp(i)
end

여기서 벡터를 활용한 for 문의 이점을 알 수 있다. 즉, iterator i는 꼭 1씩 커지거나 작아지는 방식으로 정의되지 않아도 된다는 점이다. 예를 들어 MALTAB에서는 이런 식으로 for 문이 벡터를 사용한다는 점을 응용할 수 있다.

for i = [5, 3, 4, 7]
    disp(i)
end

바로 위 코드 섹션에서는 5, 3, 4, 7이 차례대로 출력되는 것을 알 수 있다. iterator에 벡터를 곧바로 적용하지 못했다면 아래와 같은 방법을 사용할 수는 있을 것이다.

temp = [5, 3, 4, 7];
for i = 1:length(temp)
    disp(temp(i));
end

for 문과 if 문을 함께 사용하는 방법

조건문 편에서 우리는 특정 조건을 만족할 때 프로그램의 흐름을 제어할 수 있는 방법에 대해 알아본 바 있다. 이러한 프로그램 흐름 제어는 for 문을 이용할 때도 마찬가지로 적용할 수 있다. for 문을 이용해 반복 작업을 하다가 특정 조건을 만족하면 더 이상 반복 작업을 하지 않고 작업을 중단하는 것이다.

이러한 반복 작업 중 조건을 이용한 흐름 제어가 왜 필요한지 의문을 가질 수도 있다. 가령, ‘1부터 10까지 반복을 이미 시켜뒀는데 왜 5까지만 계산하고 6부터는 계산하지 않도록 하는 것인가?’와 같은 의문이다. 하지만, 어떤 경우에는 얼마만큼의 반복량이 필요한지 정확히 예측하기 어려운 경우가 발생할 수 있다. 수치해석 작업을 수행할 때에는 이론값과 계산값의 차이(오차)가 특정 조건 보다 작아지면 더 이상 계산하지 않도록 요구할 수 있다. 또, 뉴럴넷을 훈련하는 경우 훈련 데이터에 대해 충분히 training loss와 validation loss를 낮춘 뒤 훈련을 미리 종료시키면 훈련 데이터에 대한 과적합(overfitting)을 방지할 수도 있다.

for 문 중간에 탈출하기 (break)

for 문이 돌아가다가 중간에 break 명령어를 만나면 뒤에 남아있는 반복 작업은 미련없이 중단하고 for-end 구조의 end 뒤로 프로그램의 흐름이 이동하게 된다.

for i = 1:10
    if i>5
        break;    
    end
    disp(i);
end
disp('After for-end');

위 코드 섹션을 수행해보면 1부터 5까지 숫자가 출력되고 곧바로 “After for-end”가 출력되는 것을 알 수 있다.

break를 이용한 조금 더 복잡한 예시를 들어보자면 아래와 같은 일을 수행할 수 있는 것이다.

for x = 1:5000
    fx = 1/x;

    if fx < 0.001
        break;
    end
end

str = "The final x was " + x;
disp(str)

x가 1000일 때 fx가 1/1000이고, x가 1001일 때 fx가 1/1001 이다. 따라서 x는 1001일 때 if 문의 조건이 true가 되면서 break 명령어를 통해 for 문 내의 반복 작업이 더 이상 수행되지 않고 종료된다는 것을 알 수 있다.

for 문 중간에 건너 뛰고 다음 회차 계속 (continue)

또, 반복문을 이용할 때 프로그램 흐름을 제어할 수 있는 또 다른 시나리오는 특정 조건을 만족할 때에는 반복문 내의 명령어들을 스킵하고 다음 회차로 넘어가는 것이다. 이 때는 continue 명령어를 이용할 수 있다. 아래의 예시를 확인해보자.

for i = 1:5
    if i == 3
        continue;
    end
    disp(i);
end

위 코드 섹션을 실행해보면 3을 출력하는 과정은 건너 뛰고 1, 2, 4, 5만 출력되는 것을 알 수 있다. 이처럼 continue 명령어를 이용하면 continue를 만났을 때 이후의 반복 명령어들은 스킵하고 다음 반복 회차부터 반복 작업을 수행하게 된다.

벡터, 행렬, 셀을 이용해 반복하는 방법

앞서 MATLAB의 for 문은 벡터를 직접 이용한 독특한 구조를 가지고 있다고 언급한 바 있다. 그런데, 사실 for 문은 벡터 뿐만 아니라 어레이(array) 형식의 변수들을 iterator로 활용할 수 있다.

아래는 가장 간단하게 벡터를 iterator로 이용한 형식이다.

x = 1:5;
for i = x
    disp(i)
end

또, iterator에 행렬을 입력시킬 수 있다. magic(3)은 아래와 같은 값을 가진다.

     8     1     6
     3     5     7
     4     9     2

MATLAB이 행렬을 읽을 때 열 방향을 우선 방향으로 인식하기 때문에 아래의 코드 섹션은 magic(3)의 각 열이 하나씩 출력되는 것을 알 수 있다.

x = magic(3)
for i = x
    disp(i)
end

또, for 문의 iterator로 cell을 넣을 수도 있다. 아래의 코드 섹션을 수행하면 셀의 내용물들을 셀로써 호출하게 된다. 즉, {'a'}, {'b'}, {'c'}와 같은 결과를 얻게 된다.

x = {'a','b','c'};

for i = x
    disp(i)
end

심지어 for 문의 iterator에는 table 형 변수를 넣을 수도 있다. 셀에 for 문을 적용할 대와 마찬가지로 table의 각 열에 해당하는 변수값들을 테이블로써 호출하게 된다.

x = table(1:10, 2:11);

for i = x
    disp(i)
end

while-end 구조

while-end 구조는 흔히 while 문(文)이라고도 불리고, 특정 조건이 만족 될 때 만 특정 명령어 그룹을 반복하여 수행할 수 있다. MATLAB의 while 문은 하나의 while이라는 명령 문구에 end 문구가 하나씩 쌍을 이루는 식으로 구성되어 있으며, while 뒤에 논리 연산 (true 혹은 false)가 붙어있는 형식의 문법을 가지고 있다.

기본적인 while 문의 구조는 아래와 같다.

i = 1;
while (i < 10)
    disp(i)
    i = i + 1;
end

while 뒤에 i < 10 이라는 문구가 바로 논리 연산 결과물(true 혹은 false)에 해당한다. 그리고 위 코드 섹션을 수행해보면 1부터 10까지 차례대로 숫자를 출력해주는 것을 알 수 있다.

조건문이 포함된 반복문이라는 관점에서 while 문은 break를 이용한 for 문과 같은 논리 구조를 가진다고 할 수 있다.

while 문 중간에 탈출하기 (break)

for 문과 마찬가지로 while문의 경우에도 중간에 break 명령어를 만나면 뒤에 남아있는 반복 작업은 미련없이 중단하고 while-end 구조의 end 뒤로 프로그램의 흐름이 이동하게 할 수 있다. break를 사용하는 경우에는 while 뒤에 오는 조건을 항상 true로 두는 경우가 많다.

i = 1;
while true
    if i>5
        break;    
    end
    disp(i);
    i = i + 1;
end
disp('After while-end');

위 코드 섹션을 수행해보면 1부터 5까지 숫자가 출력되고 곧바로 “After while-end”가 출력되는 것을 알 수 있다.

break를 이용하여 while 문을 이용하는 것은 결국 for 문에 break를 적용하는 것과 완전히 동일한 결과를 보여줄 수 있으나 while을 이용하면 “while true”라고 작성하여 무한루프를 만들 수 있다는 점이 for 문을 사용하는 것과 차이가 있는 부분이라고 할 수 있다.

while 문 중간에 건너 뛰고 다음 회차 계속 (continue)

또, for 문과 마찬가지로 continue 명령어를 이용해 중간의 스크립트를 스킵할 수 있다. 아래의 예시를 확인해보자.

i = 0;
while (i < 5)
    i = i + 1;
    if i == 3
        continue;
    end
    disp(i);

end

위 코드 섹션을 실행해보면 3을 출력하는 과정은 건너 뛰고 1, 2, 4, 5만 출력되는 것을 알 수 있다. 이처럼 continue 명령어를 이용하면 continue를 만났을 때 이후의 반복 명령어들은 스킵하고 다음 반복 회차부터 반복 작업을 수행하게 된다.

주의 할 점은 continue를 만나면 이후의 반복 명령어가 스킵된다는 점이다. while 문을 쓸 때는 iterator를 1씩 더해주거나 하는 과정이 맨 마지막에 포함되어 있을 수 있으므로 continue 후에 iterator를 1씩 더하는 과정이 포함되지 않아야 한다. 아래의 예시는 continue를 잘못 사용하여 while 문이 끝나지 않게 되어버리는 경우이다.

% This code runs forever.
i = 1;
while (i < 5)    
    if i == 3
        continue;
    end
    disp(i);
    i = i + 1;
end

다시 설명하자면, i가 1, 2를 거쳐 3이 되었을 때 i == 3 조건을 만나 continue가 실행되고, 다시 while 문 시작으로 넘어가 i는 계속 3으로 유지되면서 while문이 끝나지 않게 되는 것이다.